-
Notifications
You must be signed in to change notification settings - Fork 86
Handle cancelled stream #65
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
…or custom cleanup after cancellation
| async def handle_stream_cancelled( | ||
| self, | ||
| thread: ThreadMetadata, | ||
| pending_items: list[ThreadItem], | ||
| context: TContext, | ||
| ): | ||
| """Perform custom cleanup / stop inference when a stream is cancelled. | ||
| Args: | ||
| thread: The thread that was being processed. | ||
| pending_items: Items that were not done streaming at cancellation time. | ||
| By default, already-streamed assistant messages, widgets, and workflows are | ||
| saved to the store during error handling prior to this method being called. | ||
| If you want to remove them from the thread, you can do so here. | ||
| (Updates you make here will not be reflected in the UI until a reload.) | ||
| context: Arbitrary per-request context provided by the caller. | ||
| """ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
New overridable ChatKitServer method. Not sure if pending_items is the right param name - they include items that were automatically persisted on cancel.
chatkit/server.py
Outdated
| case ThreadItemUpdatedEvent(): | ||
| # Keep the pending assistant message item up to date | ||
| # so that we can persist already-streamed partial content | ||
| # if the stream is cancelled. | ||
| self._update_pending_assistant_message_items( | ||
| pending_items, event | ||
| ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only applying assistant message items updates to keep the default case simple.
@weedon-openai wdyt:
- Should we apply updates for WorkflowItem and WidgetItem as well?
- Or.. since if we're not applying updates for WorkflowItem and WidgetItem automatically, should we also skip the auto-saving on cancel for these two item types?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm for the workflow item, we probably have the current workflow in memory and could just save it as is right? Technically the integration doesn't have to use our workflow utils though 🤔
Regardless, workflow deltas are really easy to apply.
Widget deltas are tricky. I kind of think we should apply them, but I'm not sure how difficult that is. Otherwise we should probably delete / revert the widget (widget streaming can happen in a response other than the one that created with widget).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
widget streaming can happen in a response other than the one that created with widget
Ahhh right good point!
Otherwise we should probably delete / revert the widget
Okay I'm leaning towards not auto-saving the widget at all and leaving the integration to handle it themselves in the overridable method.
chatkit/server.py
Outdated
| case ThreadItemUpdatedEvent(): | ||
| # Keep the pending assistant message item up to date | ||
| # so that we can persist already-streamed partial content | ||
| # if the stream is cancelled. | ||
| self._update_pending_assistant_message_items( | ||
| pending_items, event | ||
| ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm for the workflow item, we probably have the current workflow in memory and could just save it as is right? Technically the integration doesn't have to use our workflow utils though 🤔
Regardless, workflow deltas are really easy to apply.
Widget deltas are tricky. I kind of think we should apply them, but I'm not sure how difficult that is. Otherwise we should probably delete / revert the widget (widget streaming can happen in a response other than the one that created with widget).
chatkit/server.py
Outdated
| HiddenContextItem( | ||
| thread_id=thread.id, | ||
| created_at=datetime.now(), | ||
| id=self.store.generate_item_id("hidden_context", thread, context), | ||
| content="SYSTEM: The user cancelled the stream.", | ||
| ), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But what if they always use HCI with data shaped content and this breaks their converter.
Maybe HCI needs a new optional field message? Kinda cleaner than the current automatic parser approach that has to sniff the type of content.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah good point 🤔
I'm leaning towards not adding anything and instead urging the integration to write a hidden context item in their overridable method.
I also considered whether using EndOfTurnItem would make sense here.. but it might break the UI for cases where the integration decides to append some items after the stream is stopped.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 I think we should probably leave it to the integration but update all our examples with a minimal implementation of this method.
1674f22 to
4a4b81b
Compare
12827a6 to
6df9ee6
Compare
Add an overridable
ChatKitServer.handle_stream_cancelledmethod with pending items that is invoked when the stream is cancelled by the user.Add an overridable
ChatKitServer.get_stream_optionsmethod that returnsStreamOptions(allow_cancel=True)StreamOptionsEventwhich is sent at the start of_process_eventsallow_cancel=Truewill be wired up to show a stop button in the composer during the response.Tested against local branch in chatkit studio with the stop UX enabled:
stop-mid-message.mov
stop-mid-workflow.mov
stop-after-progress-update.mov